package com.doyoulike.aop;

import com.doyoulike.common.CommonResult;
import com.doyoulike.config.CusException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * 全局异常处理
 *
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass().getName());

    /**
     * 拦截自定义异常
     * @ExceptionHandler 拦截指定的异常
     */
    @ExceptionHandler(CusException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public CommonResult<Exception> notFount(CusException e) {
        logger.error("业务异常：", e);
        return CommonResult.failed(e.getMessage());
    }


   /**
    * 拦截未知的异常
    */
   @ExceptionHandler(Exception.class)
   @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
   @ResponseBody
   public CommonResult<Exception> notFount(Exception e, HttpServletRequest request) {

       // 参数解析异常
       /*if (e instanceof HttpMessageNotReadableException){
           logger.error("参数解析异常：", e);
           return new ApiResponse(ErrCodes.FAIL, "无法解析请求的参数，请检查请求的参数是否正确");
       }*/

       // ================================= 参数校验异常 begin =================================
       // MethodArgumentNotValidException 在实体类里面的校验注解,针对有@RequestBody的json入参
       /*if (e instanceof MethodArgumentNotValidException) {
           logger.error("参数校验异常：", e);
           // 如果抛出了异常，getErrorCount 一定会 > 0，返回第一条错误信息
           BindingResult result = ((MethodArgumentNotValidException) e).getBindingResult();
           return new ApiResponse(ErrCodes.FAIL, result.getAllErrors().get(0).getDefaultMessage());
           // 返回所有的错误信息
           *//*String message = "";
           for (FieldError fieldError : result.getFieldErrors()) {
               message += (message.length() > 0 ? ",":"") + fieldError.getDefaultMessage();
           }*//*
       }
       // BindException 在实体类里面的校验注解,针对普通的表单形式
       if (e instanceof BindException) {
           logger.error("参数校验异常：", e);
           BindingResult result = ((BindException) e).getBindingResult();
           return new ApiResponse(ErrCodes.FAIL, result.getAllErrors().get(0).getDefaultMessage());
       }
       // ConstraintViolationException 针对在Controller上对单个参数的校验注解
       if (e instanceof ConstraintViolationException) {
           Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) e).getConstraintViolations();
           return new ApiResponse(ErrCodes.FAIL, constraintViolations.iterator().next().getMessage());
           // 返回所有错误信息
           if (constraintViolations.size() > 0) {
               for (ConstraintViolation<?> violation : constraintViolations) {
                   message += violation.getMessage();
               }
           }
       }*/
       // ================================= 参数校验异常 end ===================================

       logger.error("未知的异常：", e);
       return CommonResult.failed(e.getMessage());
   }

}
